<template>
  <div class="message-bubble" :class="[message.flow  === 'in' ? '' : 'reverse']" ref="htmlRefHook">
    <img class="avatar"
      :src="(message?.avatar as string) || 'https://web.sdk.qcloud.com/component/TUIKit/assets/avatar_21.png'"
      onerror="this.src='https://web.sdk.qcloud.com/component/TUIKit/assets/avatar_21.png'" />
    <main class="message-area">
      <label class="name" v-if="message.flow === 'in' && message.conversationType === 'GROUP'">
        {{ message.nameCard || message.nick || message.from }}
      </label>
      <div :class="['content content-' + message.flow]" @click.prevent.right="toggleDialog">
        <slot />

        <div v-if="dropdown" ref="dropdownRef" class="dropdown-inner" @click="toggleDialog">
          <div class="dialog" :class="[message.flow === 'in' ? '' : 'dialog-right']">
            <slot name="dialog" />
          </div>
        </div>
      </div>
    </main>
    <label class="message-label fail" v-if="message.status === 'fail'" @click="resendMessage(message)">!</label>
    <label class="message-label" :class="readReceiptStyle(message)" v-if="showReadReceiptTag(message)"
      @click="showReadReceiptDialog(message)">
      <span>{{ readReceiptCont(message) }}</span>
    </label>
  </div>
  <div class="message-reference-area" :class="[message.flow === 'in' ? '' : 'message-reference-area-reverse']"
    v-if="message.cloudCustomData && referenceMessage" @click="jumpToAim(referenceMessage)">
    <div v-if="referenceMessage?.messageID && allMessageID.indexOf(referenceMessage.messageID) !== -1"
      class="message-reference-area-show">
      <p>{{ referenceForShow.nick || referenceForShow.from }}:</p>
      <div class="face-box" v-if="referenceMessage.messageType === type.typeText">
        <div v-for="(item, index) in face" :key="index">
          <span class="text-box" v-if="item.name === 'text'">{{ item.text }}</span>
          <img class="text-img" v-else-if="item.name === 'img'" :src="item.src" />
        </div>
      </div>
      <span v-if="referenceMessage.messageType === type.typeCustom">{{ referenceMessage.messageAbstract }}</span>
      <img v-if="referenceMessage.messageType === type.typeImage" class="message-img"
        :src="referenceForShow.payload.imageInfoArray[1].url" />
      <div v-if="referenceMessage.messageType === type.typeAudio" class="message-audio"
        :class="[message.flow === 'out' && 'reserve']">
        <label>{{ referenceForShow.payload.second }}s</label>
        <i class="icon icon-voice"></i>
      </div>
      <div v-if="referenceMessage.messageType === type.typeVideo" class="message-video-cover">
        <img class="message-videoimg" :src="referenceForShow.payload.snapshotUrl" />
      </div>
      <img v-if="referenceMessage.messageType === type.typeFace" class="message-img" :src="url" />
    </div>
    <div v-else class="message-reference-area-show">
      <span>{{ referenceMessage?.messageSender }}</span>
      <span>{{ referenceMessage?.messageAbstract }}</span>
    </div>
  </div>
</template>

<script setup lang="ts">
import { nextTick, ref, reactive, PropType, watchEffect } from 'vue';
import { onClickOutside, onLongPress, useElementBounding } from '@vueuse/core';

interface IMessage {
  ID?: string;
  name?: String;
  msg?: String;
  flow: String;
  src?: String;
  avatar?: String;
  conversationType?: String;
  nameCard?: String;
  nick?: String;
  from?: String;
  status?: String;
  isPeerRead?: Boolean;
  readReceiptInfo?: {
    unreadCount: number,
    readCount: number
  };
  cloudCustomData?: String;
  payload?: any
}

const props = defineProps({
  data: {
    type: Object as PropType<IMessage>,
    default: () => ({}),
  },
  messagesList: {
    type: Object,
    default: () => ({}),
  },
  isH5: {
    type: Boolean,
    default: false,
  },
  needGroupReceipt: {
    type: Boolean,
    default: false,
  },
})

defineEmits(['jumpID', 'resendMessage', 'showReadReceiptDialog'],)

const TUIServer = ''
let message = reactive<IMessage>(props.data)
const messagesList = reactive({})
const type = reactive({
  typeText: 0,
  typeCustom: 0,
  typeImage: 0,
  typeAudio: 0,
  typeVideo: 0,
  typeFace: 0
})
const referenceMessage = reactive({
  messageID: '',
  messageType: 0,
  messageAbstract: '',
  messageSender: ''
})
const referenceForShow = reactive<IMessage>({
  flow: '',
  avatar: '',
  conversationType: 'String',
  nameCard: 'String',
  nick: 'String',
  from: 'String',
  status: 'String',
  isPeerRead: true,
  readReceiptInfo: {
    unreadCount: 0,
    readCount: 0
  },
  cloudCustomData: 'String',
  payload: {}
})
const allMessageID = ref('')
const needGroupReceipt = ref(false)
const face = reactive([
  {
    name: '',
    text: '',
    src: ''
  }
])
const url = ref('')

const htmlRefHook = ref<HTMLElement | null>(null);
const dropdown = ref(false);
const dropdownRef = ref(null);

watchEffect(() => {
  message = props.data;
})

const toggleDialog = (e: any) => {
  dropdown.value = !dropdown.value;
  if (dropdown.value) {
    nextTick(() => {
      const { top } = useElementBounding(htmlRefHook);
      const ParentEle = (htmlRefHook?.value?.offsetParent as any)?.offsetParent;
      const ParentBound = useElementBounding(ParentEle);
      let T = top.value - ParentBound.top.value - 20;
      const H = (dropdownRef as any).value.children[0].clientHeight;
      if (T <= H) {
        (dropdownRef as any).value.children[0].style.top = '100%';
      } else {
        (dropdownRef as any).value.children[0].style.bottom = '100%';
      }
    });
  }
};

onClickOutside(dropdownRef, () => {
  dropdown.value = false;
});

onLongPress(htmlRefHook, toggleDialog);

const resendMessage = (message: IMessage) => {
  // ctx.emit('resendMessage', message);
};

const showReadReceiptTag = (message: any) => {
  if (needGroupReceipt.value && message.flow === 'out' && message.status === 'success' && message.needReadReceipt) return true;
  return false;
};

const readReceiptStyle = (message: IMessage) => {
  if (message.isPeerRead || message.readReceiptInfo?.unreadCount === 0) {
    return '';
  }
  return 'unRead';
};

const showReadReceiptDialog = (message: IMessage) => {
  // ctx.emit('showReadReceiptDialog', message);
};

const readReceiptCont = (message: IMessage) => {
  switch (message.conversationType) {
    case 'CONV_C2C':
      if (message.isPeerRead) {
        return '已读';
      }
      return '未读';
    case 'CONV_GROUP':
      if (message.readReceiptInfo?.unreadCount === 0) {
        return '全部已读';
      }
      if (
        message.readReceiptInfo?.readCount === 0
        || (message.readReceiptInfo?.unreadCount === undefined && message.readReceiptInfo?.readCount === undefined)
      ) {
        return '未读';
      }
      return `${message.readReceiptInfo.readCount + '人已读'}`;
    default:
      return '';
  }
};

const jumpToAim = (message: any) => {
  if (
    (referenceMessage as any)?.messageID
    && allMessageID.value.includes((referenceMessage as any)?.messageID)
  ) {
    // ctx.emit('jumpID', (referenceMessage as any).messageID);
  } else {
    const message = '无法定位到原消息';
    // handleErrorPrompts(message, props);
  }
};
</script>

<style scoped lang="scss">
.reverse {
  flex-direction: row-reverse;
  justify-content: flex-start;
}

.message-bubble {
  width: 100%;
  display: flex;
  padding-bottom: 5px;
  position: relative;

  .avatar {
    width: 28px;
    height: 28px;
    border-radius: 50%;
  }

  .message-area {
    max-width: calc(100% - 54px);
    position: relative;
    display: flex;
    flex-direction: column;
    padding: 0 8px;

    .content {
      padding: 8px;
      font-size: 14px;
      color: #000000;
      letter-spacing: 0;
      word-wrap: break-word;
      word-break: break-all;

      &-in {
        background: #fbfbfb;
        border-radius: 0px 10px 10px 10px;
      }

      &-out {
        background: #dceafd;
        border-radius: 10px 0px 10px 10px;
      }

      .text-box {
        white-space: pre-wrap;
      }
    }
  }

  .message-label {
    font-size: 12px;
    color: #b6b8ba;
    word-break: keep-all;
    position: absolute;
    bottom: -15px;
    right: 40px;
  }
}

.dropdown-inner {
  position: absolute;
  width: 100%;
  height: 100%;
  left: 0;
  top: 0;
}

.dialog {
  position: absolute;
  z-index: 1;
  margin: 10px 0;

  &-right {
    right: 0;
  }
}
</style>